import * as obvm from '../../jsruntime/runtime/vm.mjs'
class ProxyFSM {
    constructor(sceneId) {
        this.sceneId = sceneId;
    }
    PostMessage(msg) {
        let cmd = {
            cmd: 'CSNetwork-clientToServerMsg',
            arg: {
                sceneId: this.sceneId,
                vmID: msg.sender.VM.id,
                fsmID: msg.sender.id,
                msg: {
                    arg: msg.arg,
                    argType: msg.argType,
                    name: msg.name
                }
            }
        };
        (window.parent || window).postMessage(cmd, '*');
    }
}
export default class VirtualClient {
    static connections = new Map();
    static install(script) {
        script.InstallLib("CSNetwork-Client", "CSNetwork-Client", [
            // script.NativeUtil.closureReturnValue(VirtualClient.getTargetSceneName,
            //     'StringRegister', ['NObjectRegister'], true),
            // script.NativeUtil.closureReturnValue(VirtualClient.getConnection,
            //     'NObjectRegister', ['NObjectRegister'], true),
            script.NativeUtil.closureVoid(VirtualClient.connectToSerever,
                ['StringRegister', 'StringRegister', 'StringRegister', 'StringRegister'], true),
            script.NativeUtil.closureVoid(VirtualClient.disconnectFromServer,
                ['StringRegister'], true),
            // script.NativeUtil.closureVoid(VirtualClient.sendMessageToServer,
            //     ['StringRegister', 'StringRegister',], true),
            script.NativeUtil.closureVoid(VirtualClient.set_current_fsm_receive_message_from_server,
                ['StringRegister', 'StringRegister', 'LongRegister',], true),
        ]);
    }
    static handleServerToClientMsg(eventData) {
        let arg = eventData.arg;
        let sceneId = arg.sceneId;
        let VMs = VirtualClient.connections.get(sceneId);
        let vms = VMs?.keys();
        let vm_t, vm;
        while ((vm_t = vms?.next()) && vm_t.value) {
            if (vm_t.value.id == arg.vmID) {
                vm = vm_t.value;
                break;
            }
        }
        if (!vm) {
            console.error('未找到对应的虚拟机' + arg.vmID, 'sys', 4);
            return;
        }
        let titles = vm.__CSNetwork_Client_handlers.get(sceneId);
        let handlers = titles.get(arg.msg.name);
        if (handlers) {
            let proxyFSM = vm.__CSNetwork_Client_proxyFSMs.get(sceneId);
            let msg = vm.buildUsertMessage(arg.msg.name, arg.msg.argType, arg.msg.arg, proxyFSM);
            let fsms = handlers.keys();
            let fsm_t;
            while (fsm_t = fsms.next()) {
                if (fsm_t.done) {
                    break;
                }
                let fsm = fsm_t.value;
                fsm.PostMessage(msg);
            }
        }
    }
    static messageHandler(event) {
        let cmd = event.data.cmd;
        if (!cmd) {
            return;
        }
        let arg = event.data.arg;
        switch (cmd) {
            case "CSNetwork-serverToClientMsg":
                VirtualClient.handleServerToClientMsg(event.data);
                break;
            case 'CSNetwork-serverConnected':
                let sceneId = arg.sceneId;
                let VMs = VirtualClient.connections.get(sceneId);
                let vms = VMs?.keys();
                let vm_t, vm;
                while ((vm_t = vms?.next()) && vm_t.value) {
                    if (vm_t.value.id == arg.vmID) {
                        vm = vm_t.value;
                        break;
                    }
                }
                if (!vm) {
                    vm.Log('未找到对应的虚拟机', 'sys', 4);
                    return;
                }
                let info = VMs.get(vm);
                let fsm = vm.getFsmByID(arg.fsmID);
                if (fsm) {
                    info = info.get(fsm);
                    let proxyFSM = new ProxyFSM(sceneId);
                    let message = vm.buildUsertMessage(info.get('messageTitleOnConnected'), 'FSM', proxyFSM);
                    fsm.PostMessage(message);
                } else {
                    vm.Log('未找到对应的状态机', 'sys', 4);
                }
                break;
        }
    }
    // static getTargetSceneName(server) {
    //     return server.sceneName;
    // }
    // static getConnection(server) {
    //     return server.fsm;
    // }
    static connectToSerever(sceneId,
        messageTitleOnConnected, messageTitleOnDisonnected, messageTitleOnFail,
        state, fun, local, i) {
        let vm = state.fsm.VM;
        let sceneConnections = VirtualClient.connections.get(sceneId);
        if (!sceneConnections) {
            sceneConnections = new Map();
            VirtualClient.connections.set(sceneId, sceneConnections);
        }
        let config = sceneConnections.get(vm);
        if (!config) {
            config = new Map();
            sceneConnections.set(vm, config);
        }
        let handlers = config.get(state.fsm);
        if (!handlers) {
            config.set(state.fsm, new Map([
                ['messageTitleOnConnected', messageTitleOnConnected],
                ['messageTitleOnDisonnected', messageTitleOnDisonnected],
                ['messageTitleOnFail', messageTitleOnFail],
                ['messageHandlers', new Map()]]));
        }
        let cmd = {
            cmd: 'CSNetwork-connectToSerever',
            arg: {
                sceneId,
                vmID: vm.id,
                fsmID: state.fsm.id
            }
        };
        (window.parent || window).postMessage(cmd, '*');
    }
    static disconnectFromServer(sceneId, state, fun) {
        let vm = state.fsm.VM;
        if (vm.__CSNetwork_Client && vm.__CSNetwork_Client.delete(sceneId)) {
            let cmd = {
                cmd: 'CSNetwork-disconnectFromServer',
                arg: {
                    sceneId
                }
            };
            (window.parent || window).postMessage(cmd, '*');
        } else {
            vm.Log('服务器未连接', 'sys', 4, state, fun);
        }
    }
    static sendMessageToServer(sceneId, title, message, state, fun) {
        let vm = state.fsm.VM;
        if (vm.__CSNetwork_Client && vm.__CSNetwork_Client.delete(sceneId)) {
            let cmd = {
                cmd: 'CSNetwork-disconnectFromServer',
                arg: {
                    sceneId, title, message
                }
            };
            (window.parent || window).postMessage(cmd, '*');
        } else {
            vm.Log('服务器未连接', 'sys', 4, state, fun);
        }
    }
    static set_current_fsm_receive_message_from_server(sceneId, title, enabled, state, fun) {
        let vm = state.fsm.VM;
        if (enabled) {
            if (!vm.__CSNetwork_Client_handlers) {
                vm.__CSNetwork_Client_handlers = new Map();
                vm.__CSNetwork_Client_proxyFSMs = new Map();
            }
            if (!vm.__CSNetwork_Client_handlers.has(sceneId)) {
                vm.__CSNetwork_Client_handlers.set(sceneId, new Map());
            }
            let titles = vm.__CSNetwork_Client_handlers.get(sceneId);
            if (!titles.has(title)) {
                titles.set(title, new Map());
            }
            let handlers = titles.get(title);
            handlers.set(state.fsm, true);
        } else if (vm.__CSNetwork_Client_handlers) {
            let scenes = vm.__CSNetwork_Client_handlers;
            if (scenes.has(sceneId)) {
                let titles = scenes.get(sceneId);
                if (titles.has(title)) {
                    let handlers = titles.get(title);
                    handlers.delete(state.fsm);
                }
            }
        }
    }
}
window.addEventListener('message', VirtualClient.messageHandler);